using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq.Expressions;
using System.Reflection;

namespace SmartClientPlatform.RemoteClientBase
{
    internal static class MetaDataProvider
    {
        public static string GetRefPropertyName<T1, T2>(
            this Expression<Func<T1, EntitySet<T2>>> expression) where T2 : class
        {
            return GetRelatedPropertyName<T2>(((MemberExpression)expression.Body).Member);
        }

        private static string GetRelatedPropertyName<T2>(ICustomAttributeProvider memberInfo)
        {
            var customAttributes = memberInfo
                .GetCustomAttributes(typeof(AssociationAttribute), true);
            if (customAttributes.Length != 1)
            {
                throw new ApplicationException();
            }
            var relationName = ((AssociationAttribute)customAttributes[0]).Name;
            foreach (var propertyInfo in typeof(T2).GetProperties())
            {
                var customAttributes2 = propertyInfo
                    .GetCustomAttributes(typeof(AssociationAttribute), true);
                switch (customAttributes2.Length)
                {
                    case 0:
                        break;
                    case 1:
                        if (((AssociationAttribute)customAttributes2[0]).Name == relationName)
                        {
                            return propertyInfo.Name;
                        }
                        break;
                    default:
                        throw new ApplicationException();
                }
            }
            throw new ApplicationException();
        }

        public static string GetSetPropertyName<T1, T2>(string propertyName)
        {
            return GetRelatedPropertyName<T2>(typeof(T1).GetProperty(propertyName));
        }

        public static string GetPropertyName<T1, T2>(
            this Expression<Func<T1, T2>> expression)
        {
            return ((MemberExpression)expression.Body).Member.Name;
        }

        public static IEnumerable<string> GetPropertiesMames<T>()
        {
            foreach (var propertyInfo in typeof (T).GetProperties())
            {
                if (propertyInfo.GetCustomAttributes(typeof(ColumnAttribute), true)
                    .Length > 0)
                {
                    yield return propertyInfo.Name;
                }
            }
        }
    }
}